package Main;

import javax.microedition.io.Connector;
import javax.microedition.lcdui.StringItem;
import javax.microedition.sensor.*;

   class Accelerometer implements DataListener {

       /*
        * Returns the players paddle position as a normalised double from 0 to 1
        */
       double getMax() { return acc_max; } double getMin() { return acc_min; }
       void setMax(double mx) { acc_max = mx; acc_range = acc_max-acc_min; } void setMin(double mn) { acc_min = mn; acc_range = acc_max-acc_min; }

       SensorInfo[] sensors;
       String sensor_url = "";
       StringItem accString = new StringItem("Accelerometer", "");
       double acc_min = Double.MAX_VALUE, acc_max = Double.MIN_VALUE, acc_range = 1;
       int acc_type = 0x00;
       MeasurementRange[] range;
       SensorConnection conn;

       final int buffer = 10;

       double[] acc_data = new double[3]; // x y z

       // constructor
       public Accelerometer()
       {
           conn = InitAccelerometer();
           // PowerPongMIDlet.startMainThread(); // mainThread.start();
       }
       
       public void EnableAccelerometer()
       {
           if(conn != null)
           {
               try
               {
                   conn.setDataListener(this, buffer);
               }
               catch(Exception e)
               {
                   accString.setText("Data Listener error");
               }
           }
       }

       // find and initiate accelerometer 
       private SensorConnection InitAccelerometer()
       {
           try
           {
               boolean sensor_found = false;

               sensors = SensorManager.findSensors("sensor:acceleration");
               accString.setText("Found " + sensors.length + " sensors");

               if(sensors.length == 0) return null;

               int datatypes[] = new int[sensors.length];

               for(int i = 0 ; i < sensors.length ; i++)
               {
                   ChannelInfo[] channels = sensors[i].getChannelInfos();

                   if(channels.length == 0)
                       continue;
                   datatypes[i] = sensors[i].getChannelInfos()[0].getDataType();

                   sensor_url = sensors[i].getUrl();
                   acc_type = datatypes[i];

                   if(sensor_url.length() != 0 && datatypes[i] == ChannelInfo.TYPE_INT) break;

               }

               return (SensorConnection) Connector.open(sensor_url);
           }
           catch(Exception e)
           {
               return null;
           }
       }

       double oldPos = 0;
       // receive new data from the accelerometer
       public void dataReceived(SensorConnection sc, Data[] datas, boolean bln)
       {
            // this.setTitle("x value = " + datas[0].getDoubleValues()[0]);
            if(acc_type == ChannelInfo.TYPE_DOUBLE)
                acc_data[0] = average(datas[0].getDoubleValues());
            else if(acc_type == ChannelInfo.TYPE_INT)
                acc_data[0] = average(datas[0].getIntValues());

            // adjust maximum and minimum values to keep range calibrated
            if(acc_data[0] < acc_min)
                acc_min = acc_data[0];
            if(acc_data[0] > acc_max)
                acc_max = acc_data[0];
            acc_range = acc_max - acc_min;
            
            double new_paddle_position = (acc_data[0] - acc_min) / acc_range;
            double abs_change = Math.abs(Main.PowerPongMIDlet.gfx.getServerAccData() - new_paddle_position);
            double abs_dead_zone = Math.abs(new_paddle_position - 0.5);
            if(abs_dead_zone > 0.07)
            {
                if(abs_change > 0.01)
                {
                    Main.PowerPongMIDlet.gfx.setServerAccData(new_paddle_position);
                    Main.PowerPongMIDlet.bt.SendString("C " + new_paddle_position);
                    oldPos = new_paddle_position;
                }
            }
            else
            {
                if(oldPos != 0.5)
                {
                    Main.PowerPongMIDlet.gfx.setServerAccData(0.5);//paddle_position + (new_paddle_position - paddle_position) / abs_change * 0.5;
                    Main.PowerPongMIDlet.bt.SendString("C " + 0.5);
                    oldPos = 0.5;
                }
            }
            

//            Main.PowerPongMIDlet.gfx.setTitle("position: " + Main.PowerPongMIDlet.gfx.getPaddlePosition()); 
           
        }
       
       // determine average of array to smooth accelerometer values
       private double average(double[] arr)
       {
           double total = 0;
           for (int a = 0; a < arr.length; a++) { total += arr[a]; }
           return total / arr.length;
       }

       // determine average of array to smooth accelerometer values
       private double average(int[] arr)
       {
           double total = 0;
           for (int a = 0; a < arr.length; a++) { total += (double) arr[a]; }
           return total / arr.length;
       }
    }